package com.nineclock.auth.aop;

import com.nineclock.auth.entity.IntegrationAuthenticationEntity;
import com.nineclock.auth.entity.NcOauthTokenDTO;
import com.nineclock.auth.threadlocal.IntegrationAuthenticationHolder;
import com.nineclock.auth.threadlocal.UserHolder;
import com.nineclock.common.entity.Result;
import com.nineclock.common.entity.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 *
 * @Aspect: 配置该类为切面
 * @Version 1.0
 */
@Component
@Aspect
@Slf4j
public class AuthTokenAspect {

    @Autowired
    HttpServletRequest request;

    /**
     * ProceedingJoinPoint joinPoint: 连接点
     * @param joinPoint
     * @return
     */
    @Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            //前置增强
            //1. 从请求对象中获取参数， 封装成 认证实体类
            IntegrationAuthenticationEntity entity = new IntegrationAuthenticationEntity();
            //获取认证类型
            String auth_type = request.getParameter("auth_type");
            entity.setAuthType(auth_type);
            //其他的参数
            Map<String, String[]> map = request.getParameterMap();
            entity.setAuthParameters(map);

            //2. 存储在当前线程
            IntegrationAuthenticationHolder.set(entity);
            //调用原始方法, 返回值 是原始方法的返回值
            Object result = joinPoint.proceed();
            //后置增强： 要对返回值 数据进行重新封装
            ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity<OAuth2AccessToken>) result;

            Result res;
            //如果验证成功
            if(responseEntity.getStatusCode().is2xxSuccessful()){
                //封装 前端需要的 token数据格式
                NcOauthTokenDTO ncOauthTokenDTO = new NcOauthTokenDTO();

                OAuth2AccessToken body = responseEntity.getBody();
                ncOauthTokenDTO.setOauth2AccessToken(body);
                //从线程中获取userInfo
                UserInfo userInfo = UserHolder.get();
                ncOauthTokenDTO.setUser(userInfo); //需要userInfo信息

                res = Result.success(ncOauthTokenDTO);
            }
            //否则验证失败
        else {
            log.error("获取令牌失败："+responseEntity.getStatusCode().toString());
            res = Result.errorCodeMessage(401, "获取令牌失败!!");
        }

        //数据返回
        return ResponseEntity.ok(res);

    } finally {
        //移除线程中的 认证实体对象
        IntegrationAuthenticationHolder.remove();
        //移除线程中的 userInfo对象
        UserHolder.remove();
        }


    }
}
